package org.gridlab.gridsphere.services.visualization;

import java.io.PrintWriter;
import java.io.IOException;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;
import javax.portlet.PortletContext;
import org.gridlab.gridsphere.services.visualization.DataProvider;
import org.gridlab.gridsphere.services.visualization.ChartGenerator;
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;

/**
 * Implementacja klasy abstrakcyjnej ChartGenerator pozwalająca na osadzanie wykresów typu Scatter plot 3D w postaci appletów
 * @author Pawel Koperek, Krzysztof Goj
 */
public class Scatterplot3DChartGenerator extends ChartGenerator {

	private String dataUrl;    
	private String systemPath;
	private static String cType = "SCATTERPLOT3D";
	private static int counter = 0;

    /**
     * Tworzy nowy obiekt typu ScatterplotAppletChartGenerator
     * @param dp DataProvider z danymi dla tego typu wykresu
     * @param c Kontekst portletu
     */
    public Scatterplot3DChartGenerator(DataProvider dp, PortletContext c) {
        super(dp, c);
    }

    /**
     * Generuje kod HTML osadzający applet oraz wyświetla go za pomocą portletu
     * @param request Obiekt żądania od klienta
     * @param response Obiekt odpowiedzi do klienta
     * @throws java.io.IOException Wyjętek rzucany, gdy wystąpi błąd I/O
     * @throws org.gridlab.gridsphere.services.visualization.ChartGeneratorException 
     */
    public void embedChart(RenderRequest request, RenderResponse response) throws IOException, ChartGeneratorException {
	PrintWriter out = new PrintWriter(response.getWriter());

	systemPath = context.getRealPath(request.getContextPath());
	systemPath = systemPath.substring(0,systemPath.lastIndexOf('/'));
	prepare();
	
	out.print("<applet code=\"visualizer/Main.class\" width=\"640\" height=\"480\" ARCHIVE=\"");
	out.println( request.getContextPath() + "/charts/Visualizer.jar\">");
	out.print("<param name=\"DATAURL\" value=\"" + request.getScheme() + "://" + 
		request.getServerName() + ":" + request.getServerPort() + 
		request.getContextPath() + "/charts/" + dataUrl + "\">" );
	out.print("<param name=\"CHARTTYPE\" value=\"" + cType + "\">" );
	out.println("</applet>");
    }

    /**
     * Generuje wykres na podstawie danych
     */
    protected void generateChart() {
	ObjectOutputStream fos = null;
	dataUrl =  getURLNamePart() + ".dat";

	try {
		fos = new ObjectOutputStream( new FileOutputStream(systemPath + "/charts/" + dataUrl) );

		// Data export

		fos.writeInt(dataProvider.getSeriesCount());

		for(int i=0;i<dataProvider.getSeriesCount();i++) {
			fos.writeObject( dataProvider.getSeriesName(i) );

			Double[][] data = (Double[][]) dataProvider.getData(i);

			fos.writeInt(3*data.length);

			for(int j=0;j<data.length;j++) {
				fos.writeDouble(data[j][0].doubleValue());
				fos.writeDouble(data[j][1].doubleValue());
				fos.writeDouble(data[j][2].doubleValue());
                        }
		}
		
	} catch(java.io.FileNotFoundException e) {
		e.printStackTrace();
	} catch(java.io.IOException e) {
		e.printStackTrace();
	} finally {
		if(fos!=null) {
			try {
				fos.close();
			} catch(java.io.IOException e) {
				e.printStackTrace();
			}
		}
	}
    }

    /**
     * Zwraca typ danych wymagany przez ten ChartGenerator
     * @return Typ danych wymagany przez ten ChartGenerator czyli Double[][].class
     */
    protected Class dataType() {return Double[][].class;}
    /**
     * Sprawdza czy dostarczone dane są poprawne
     * @throws org.gridlab.gridsphere.services.visualization.ChartGeneratorException 
     */
    protected void checkData() throws ChartGeneratorException {
        super.checkData();
        for(int i=0; i<dataProvider.getSeriesCount(); ++i) {
            Double[][] data = (Double[][]) dataProvider.getData(i);
            for(int j=0; j<data.length; ++j)
                if(data[j].length != 3)
                    throw new ChartGeneratorException("Data series must be array of 3 Double arrays");
        }
    }
}

